package com.echatim;

import com.commom.Config;
import com.echatim.broker.SocketIOBroker;
import com.event.AppStartup;
import com.event.EventBus;
import com.utils.Streams;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.PropertySource;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.*;

/**
 * springboot-main
 */


@EnableScheduling
@EnableAsync
@EnableTransactionManagement
@EnableConfigurationProperties
@EnableSwagger2
@SpringBootApplication
@ComponentScan(basePackages = {
        "com.echatim.config",
        "com.echatim.controller",
        "com.echatim.service",
        "com.echatim.broker",
        "com.echatim.filter",
        "com.exception"})
@MapperScan("com.echatim.mapper*")
public class Application {
    private final static Logger logger = LoggerFactory.getLogger(Application.class);
    private static ApplicationContext ctx;

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);

        app.setBannerMode(Banner.Mode.OFF);
        ConfigurableApplicationContext context = app.run(args);
        ctx = context;
        ApplicationWrapper.setContext(ctx);
        context.getBean(EventBus.class).post(new AppStartup()); // app 启动广播通知
        int port = Integer.parseInt(Optional.ofNullable(context.getEnvironment().getProperty("server.port")).orElse("0"));
        int socketIOPort = Integer.parseInt(Optional.ofNullable(context.getEnvironment().getProperty("socketio.port")).orElse("0"));
        logger.info("PortalApplication is success!");
        System.err.println("swagger test started. http://localhost:" + port +"/swagger-ui.html");
        System.err.println("socket.io started. http://localhost:" + socketIOPort);

        dumpEnv(context);
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println(" shutdown SocketIOBroker");
            SocketIOBroker socketIOBroker = ctx.getBean(SocketIOBroker.class);
            socketIOBroker.destroy();
        }));
    }


    private static void dumpEnv(ConfigurableApplicationContext context){
        Map<String, Set<String>> configKey = new HashMap<>();
        Iterator<PropertySource<?>> iterator = context.getEnvironment().getPropertySources().iterator();
        while (iterator.hasNext()){
            PropertySource<?> propertySource = iterator.next();
            if(propertySource.getName().startsWith("applicationConfig:") && propertySource.getSource() instanceof Map){
                Set<String> keys = configKey.getOrDefault(propertySource.getName(), new HashSet<>());
                ((Map)propertySource.getSource()).keySet().forEach(k-> keys.add(String.valueOf(k)));
                configKey.put(propertySource.getName(), keys);
            }
        }

        Set<String> allKeys = new TreeSet<>(Streams.listFlatMap(configKey.values(), ArrayList::new));
        logger.info("=== show springboot application-configure. [active:{}] === ", Config.get(context, "spring.profiles.active"));
        allKeys.forEach(v->{
            logger.info("==> {} = {}", v, Config.get(context, v));
        });
        logger.info(" 欢迎使用E聊(www.echat.work),技术交流QQ群:471688937");
    }

}
